home *** CD-ROM | disk | FTP | other *** search
/ Programming a Multiplayer FPS in DirectX / Programming a Multiplayer FPS in DirectX (Companion CD).iso / DirectX / dxsdk_oct2004.exe / dxsdk.exe / Documentation / DirectX9 / directx9_m.chm / directx / code / lookup.js < prev    next >
Encoding:
Text File  |  2004-09-30  |  50.4 KB  |  2,036 lines

  1. <![CDATA[
  2. // LOOKUP.JS code BEGIN  //at
  3. var gsExt = ".asp";
  4. var gaMapLang2SubNode = {'cpp' : 'iface', 'vb' : 'object'};
  5. var gaMapScope = {'cpp' : '::', 'vb' : '.'};
  6. var gaMapAttr = {'cpp' : 'iid'}; // allows the author to resolve an ambiguous reference to a shared member
  7. var gaMapAuto = {'cpp' : 'autoiid'}; // pointing to a shared topic we need to auto-resolve since the links differs depending on context
  8. var gaMapPNRN = {'rn' : 'runtime name', 'pn' : 'persistent name', 'name' : 'name'};
  9. var gaDLangMap = {'self' : 'devlang', 'ext' : 'dlang'}; // handle name difference: metadata/devlang vs. targ/dlang
  10. var aFlagAttrMap = {'cpp' : 'name', 'scr' : 'value', 'vb' : 'name'}; // map devlang to appropriate attribute in a flag
  11.  
  12. // List of regular expressions for URLs that are known to be Microsoft sites
  13. var gaMSSiteREs = [ /microsoft\.com/i, /msn\.com/i, /gotdotnet\.com/i, /biztalk\.org/i, /bcentral\.com/i, /zone\.com/i ];
  14.  
  15. // BUGBUG: Hardcoded extension map.
  16. var gaExtMap = {'asp' : 'htm'};
  17.  
  18. var NODE_TEXT = 3;
  19.  
  20. // simple source object; use an instance in place of an xref node when performing a lookup
  21. function CSimpleSrc(sRID, sCurLang)
  22. {
  23.   this.rid = sRID;
  24.   this.devlang = sCurLang;
  25. }
  26.  
  27. // sets a flag indicating the object is a self reference
  28. CSimpleSrc.prototype.SetSelf = function(b)
  29. {
  30.   this.self = b;
  31. }
  32.  
  33. CSimpleSrc.prototype.IsSelfReference = function()
  34. {
  35.   return (this.self ? true : false);
  36. }
  37.  
  38. /////////////////////////////////////////////////////////////
  39.  
  40. // encapsulates an a cached target node
  41. function CCacheItem(oTNode, iRefCount)
  42. {
  43.   Node2Object(oTNode, this, "_");
  44.  
  45.   this._targetNode = oTNode;
  46.   this._cRefs = iRefCount; // number of references to this target
  47. }
  48.  
  49. /////////////////////////////////////////////////////////////
  50.  
  51. function CLookup(oCtx)
  52. {
  53.   this._oCtx = oCtx;
  54.   this._error = "";
  55.   this._fBadDataSrc = false;
  56.   this._cache = new Array();
  57.   this._aTLAs = new Array();  //at
  58.   this._sTLA = "";            //at
  59.   this._bTLACap = false;      //at
  60.   this._bTLAPlural = false;   //at
  61.   this._oAcronym = null;      //at
  62. }
  63.  
  64. CLookup.prototype.ClearError = function()
  65. {
  66.   this._error = "";
  67. }
  68.  
  69. // Attempt to pull the cached item from the local hash, or cache it
  70. CLookup.prototype.RetrieveCachedItem = function(sRID, bNoIncRefs)
  71. {
  72.   var oCacheItem = this._cache[sRID];
  73.   if (oCacheItem)
  74.   {
  75.     if (!bNoIncRefs)
  76.     {
  77.       oCacheItem._cRefs++
  78.     }
  79.   }
  80.   else
  81.   {
  82.     oCacheItem = this.CacheItem(sRID, bNoIncRefs);
  83.   }
  84.  
  85.   return oCacheItem;
  86. }
  87.  
  88. // Lookup the specified rid in the store.
  89. //at *** Rewritten for LuCache.
  90. CLookup.prototype.RetrieveTarget = function(sRID)
  91. {
  92.   var bOk = false;
  93.   var sTargXML = null;
  94.   var sTPath = this._oCtx._sDrive + this._oCtx.GetPathOf("targets");
  95.   var oTNode = null;
  96.   var oData = null;
  97.   var bLuCache = this._oCtx.CacheLookups();
  98.  
  99.   oData = this.EnsureData(bLuCache);
  100.   bLuCache = this._oCtx.CacheLookups();
  101.  
  102.   if (bLuCache && oData)
  103.   {
  104.     // Try to use the LuCache Lookup Cache.
  105.     try
  106.     {
  107.       // Call LuCache to lookup the RID and get back the node-xml.
  108.       sTargXML = oData.LookupId(sRID, sTPath);
  109.     }
  110.     catch(e)
  111.     {
  112.       this._error = "LuCache failure." + e.description;
  113.       sTargXML = null;
  114.     }
  115.     if (sTargXML)
  116.     {
  117.       var oTDom = this._oCtx._oTDom;
  118.  
  119.       // Now use "mini-dom" node to load node-xml and get a node.
  120.       oTDom.async = false;
  121.       oTDom.loadXML(sTargXML);
  122.       oTNode = oTDom.documentElement;
  123.       if (oTNode)
  124.         bOk = true;
  125.       else
  126.         this._error = "cannot load target node.";
  127.     }
  128.     else
  129.       this._error = "rid not found (" + sRID + ").";
  130.   }
  131.   else
  132.   {
  133.     // Try to use a loaded DOM for lookups.
  134.     if (bLuCache && !oData)
  135.       oData = this.EnsureData(false);
  136.     if (oData)
  137.     {
  138.       // oTNode = oData.selectSingleNode("id('" + sRID + "')");
  139.       // Use faster nodeFromID.
  140.       oTNode = oData.nodeFromID(sRID);
  141.       if (oTNode)
  142.         bOk = true;
  143.       else
  144.         this._error = "rid not found (" + sRID + ").";
  145.     }
  146.     else
  147.       this._error = "cannot create access to targets.";
  148.   }
  149.  
  150.   if (!bOk)
  151.     oTNode = null;
  152.  
  153.   return oTNode;
  154. }
  155.  
  156. // Get topicinfo node from topinfo.xml. //at
  157. CLookup.prototype.RetrieveTopicInfo = function(sID)
  158. {
  159.   var bOk = false;
  160.   var sTIXML = null;
  161.   var sTIPath = this._oCtx._sDrive + this._oCtx.GetPathOf("topinfo");
  162.   var oTINode = null;
  163.   var oData = null;
  164.   var bLuCache = this._oCtx.CacheLookups();
  165.  
  166.   oData = this.EnsureTIData(bLuCache);
  167.   bLuCache = this._oCtx.CacheLookups();
  168.  
  169.   if (bLuCache && oData)
  170.   {
  171.     // Try to use the LuCache Lookup Cache.
  172.     try
  173.     {
  174.       // Call LuCache to lookup the RID and get back the node-xml.
  175.       sTIXML = oData.LookupId(sID, sTIPath);
  176.       if (!sTIXML)
  177.         this._error = "id not found (" + sID + ").";
  178.     }
  179.     catch(e)
  180.     {
  181.       this._error = "LuCache failure. " + e.description;
  182.       sTIXML = null;
  183.     }
  184.     if (sTIXML)
  185.     {
  186.       var oTIDom = this._oCtx._oTDom;
  187.  
  188.       // Now use "mini-dom" node to load node-xml and get a node.
  189.       oTIDom.async = false;
  190.       oTIDom.loadXML(sTIXML);
  191.       oTINode = oTIDom.documentElement;
  192.       if (oTINode)
  193.         bOk = true;
  194.       else
  195.         this._error = "cannot load topic info node.";
  196.     }
  197.   }
  198.   else
  199.   {
  200.     // Try to use a loaded DOM for lookups.
  201.     if (bLuCache && !oData)
  202.       oData = this.EnsureTIData(false);
  203.     if (oData)
  204.     {
  205.       // oTNode = oData.selectSingleNode("id('" + sID + "')");
  206.       // Use faster nodeFromID.
  207.       oTINode = oData.nodeFromID(sID);
  208.       if (oTINode)
  209.         bOk = true;
  210.       else
  211.         this._error = "id not found (" + sID + ").";
  212.     }
  213.     else
  214.     {
  215.       if (!this._error)
  216.         this._error = "cannot create access to topic info.";
  217.     }
  218.   }
  219.  
  220.   if (!bOk)
  221.     oTINode = null;
  222.  
  223.   return oTINode;
  224. }
  225.  
  226. // Get acronym node (ie, using TLA rid) from acronyms.xml. //at
  227. CLookup.prototype.RetrieveAcronym = function(sID)
  228. {
  229.   var bOk = false;
  230.   var sAcXML = null;
  231.   var sAcPath = this._oCtx._sDrive + this._oCtx.GetPathOf("acronyms");
  232.   var sAcDtdPath = this._oCtx._sDrive + this._oCtx.GetPathOf("acronymsdtd");
  233.   var oAcNode = null;
  234.   var oData = null;
  235.   var bLuCache = this._oCtx.CacheLookups();
  236.  
  237.   oData = this.EnsureAcData(bLuCache);
  238.   bLuCache = this._oCtx.CacheLookups();
  239.  
  240.   if (bLuCache && oData)
  241.   {
  242.     // Try to use the LuCache Lookup Cache.
  243.     try
  244.     {
  245.       // Call LuCache to lookup the RID and get back the node-xml.
  246.       sAcXML = oData.LookupId(sID, sAcPath);
  247.       if (!sAcXML)
  248.         this._error = "id not found (" + sID + ").";
  249.     }
  250.     catch(e)
  251.     {
  252.       this._error = "LuCache failure. " + e.description;
  253.       sAcXML = null;
  254.     }
  255.     if (sAcXML)
  256.     {
  257.       var oAcDom = this._oCtx._oTDom;
  258.       var sXML = '<!DOCTYPE acronym SYSTEM "'+sAcDtdPath+'" []>'+sAcXML;
  259.  
  260.       // Now use "mini-dom" node to load node-xml and get a node.
  261.       oAcDom.async = false;
  262.       oAcDom.loadXML(sXML);
  263.       oAcNode = oAcDom.documentElement;
  264.       if (oAcNode)
  265.         bOk = true;
  266.       else
  267.         this._error = "cannot load acronym node.";
  268.     }
  269.   }
  270.   else
  271.   {
  272.     // Try to use a loaded DOM for lookups.
  273.     if (bLuCache && !oData)
  274.       oData = this.EnsureAcData(false);
  275.     if (oData)
  276.     {
  277.       // oAcNode = oData.selectSingleNode("id('" + sID + "')");
  278.       // oAcNode = oData.selectSingleNode("/acroot/inetsdk:acronyms/acronym[@id='"+sID+"']");
  279.       // Use faster nodeFromID.
  280.       oAcNode = oData.nodeFromID(sID);
  281.       if (oAcNode)
  282.         bOk = true;
  283.       else
  284.         this._error = "id not found (" + sID + ").";
  285.     }
  286.     else
  287.     {
  288.       if (!this._error)
  289.         this._error = "cannot create access to acronyms.";
  290.     }
  291.   }
  292.  
  293.   if (oAcNode && oAcNode.getAttribute("deprecated"))
  294.     bOk = false;
  295.  
  296.   if (!bOk)
  297.     oAcNode = null;
  298.  
  299.   return oAcNode;
  300. }
  301.  
  302. // Resets firsttime status for all TLAs encountered so far in the
  303. // page transformation. Use with care. //at
  304. CLookup.prototype.ResetTLA = function()
  305. {
  306.   var i = 0;
  307.  
  308.   if (this._aTLAs)
  309.   {
  310.     delete this._aTLAs;
  311.     this._aTLAs = new Array();  //at
  312.   }
  313.  
  314.   return false;
  315. }
  316.  
  317. // Determine if the authored TLA is in acronyms.xml.
  318. // Called directly from XSL. //at
  319. CLookup.prototype.IsTLA = function(oTLA)
  320. {
  321.   var bYes = false;
  322.   var sRid = null;
  323.   var oAc = null;
  324.   var sVal = "";
  325.  
  326.   this._sTLA = "";
  327.   this._bTLACap = false;
  328.   this._bTLAPlural = false;
  329.   this._oAcronym = null;
  330.  
  331.   if (oTLA)
  332.   {
  333.     sRid = oTLA.getAttribute("rid");
  334.     if (sRid)
  335.     {
  336.       oAc = this.RetrieveAcronym(sRid);
  337.       if (oAc)
  338.       {
  339.         sVal = oTLA.getAttribute("initcap");
  340.         if (sVal)
  341.           this._bTLACap = true;
  342.  
  343.         sVal = oTLA.getAttribute("plural");
  344.         if (sVal)
  345.           this._bTLAPlural = true;
  346.  
  347.         this._oAcronym = oAc;
  348.         bYes = true;
  349.       }
  350.     }
  351.   }
  352.  
  353.   return bYes;
  354. }
  355.  
  356. // In the current document, determine if this node is the first
  357. // TLA using its associated ID (rid). Use associative array to
  358. // remember the TLA Rids encountered.  //at
  359. CLookup.prototype.IsFirstTLA = function(sRid)
  360. {
  361.   var bYes = false;
  362.   var bFound = false;
  363.  
  364.   if (sRid)
  365.   {
  366.     bFound = this._aTLAs[sRid];
  367.     if (!bFound)
  368.     {
  369.       this._aTLAs[sRid] = true;
  370.       bYes = true;
  371.     }
  372.   }
  373.  
  374.   return bYes;
  375. }
  376.  
  377. // Workhorse internal function to build the TLA substitution
  378. // string when nested TLA strings are being appended.
  379. // Note the indirect recursive call relation between this
  380. // function and MakeTLA. //at
  381. CLookup.prototype.NestTLA = function(oAcNode)
  382. {
  383.   var bOk = false;
  384.   var oAcNested = null;
  385.   var aNested = null;
  386.   var oNested = null;
  387.   var sRidNested = "";
  388.   var sText = "";
  389.   var sChar = "";
  390.   var i = 0;
  391.  
  392.   if (oAcNode)
  393.   {
  394.     aNested = oAcNode.selectNodes("tla");
  395.     if (aNested && aNested.length>0)
  396.     {
  397.       for(i=0; i<aNested.length; i++)
  398.       {
  399.         oNested = aNested[i];
  400.         if (oNested)
  401.         {
  402.           sRidNested = oNested.getAttribute("rid");
  403.           if (sRidNested)
  404.           {
  405.             oAcNested = this.RetrieveAcronym(sRidNested);
  406.             bOk = this.MakeTLA(oAcNested);
  407.           }
  408.         }
  409.       }
  410.  
  411.       sText = oAcNode.text;
  412.       sChar = sText.substr(0,1);
  413.       sChar = sChar.toLowerCase();
  414.       switch (sChar)
  415.       {
  416.         case ".":
  417.           sText = sText.toLowerCase();
  418.           if (sText == ".net")
  419.             this._sTLA += " "+oAcNode.text;
  420.           else
  421.             this._sTLA += oAcNode.text;
  422.           break;
  423.         case " ":
  424.         case ",":
  425.         case ":":
  426.         case ";":
  427.           this._sTLA += oAcNode.text;
  428.           break;
  429.         default:
  430.           this._sTLA += " "+oAcNode.text;
  431.           break;
  432.       }
  433.     }
  434.     else
  435.       this._sTLA += oAcNode.text;
  436.   }
  437.  
  438.   return bOk;
  439. }
  440.  
  441. // Workhorse internal recursive function that builds the substitution
  442. // string for a TLA.  It determines if the Acronym node (oAc) should
  443. // be expanded to its primary or secondary representation.
  444. // According to MSTE, the first instance of a trademark (TM) or
  445. // registered trademark (R) name should include the trademark marking.
  446. // Editorially, this should also mean that the first use of a
  447. // product name within a topic should be referenced by a TLA that
  448. // has the proper marking.  Subsequent instances of the trademarked
  449. // names within the same topic should not show the trademark
  450. // marking. Note the indirect recursive call relation between this
  451. // function and NestTLA. //at
  452. CLookup.prototype.MakeTLA = function(oAc)
  453. {
  454.   var bOk = false;
  455.   var bFirst = true;
  456.   var sRid = "";
  457.   var oPrimary = null;
  458.   var oSecondary = null;
  459.  
  460.   if (oAc)
  461.   {
  462.     oSecondary = oAc.selectSingleNode("secondary");
  463.     oPrimary = oAc.selectSingleNode("primary");
  464.     sRid = oAc.getAttribute("id");
  465.     bFirst = this.IsFirstTLA(sRid);
  466.     if (bFirst)
  467.       bOk = this.NestTLA(oPrimary);
  468.     else
  469.     {
  470.       if (oSecondary)
  471.         bOk = this.NestTLA(oSecondary);
  472.       else
  473.         bOk = this.NestTLA(oPrimary);
  474.     }
  475.   }
  476.  
  477.   return bOk;
  478. }
  479.  
  480. //at Make Plural TLA.
  481. CLookup.prototype.MakeTLAP = function(oAc)
  482. {
  483.   var bOk = false;
  484.   var bFirst = true;
  485.   var sRid = "";
  486.   var oPrimary = null;
  487.   var oSecondary = null;
  488.  
  489.   if (oAc)
  490.   {
  491.     oSecondary = oAc.selectSingleNode("secondaryp");
  492.     oPrimary = oAc.selectSingleNode("primaryp");
  493.     sRid = oAc.getAttribute("id");
  494.     bFirst = this.IsFirstTLA(sRid);
  495.     if (bFirst)
  496.       this.NestTLA(oPrimary);
  497.     else
  498.     {
  499.       if (oSecondary)
  500.         this.NestTLA(oSecondary);
  501.       else
  502.         this.NestTLA(oPrimary);
  503.     }
  504.     bOk = true;
  505.   }
  506.  
  507.   return bOk;
  508. }
  509.  
  510. // Just return the TLA's substitution string.
  511. // Must be called immediately after IsTLA has been called.
  512. // Called internally or directly from XSL. //at
  513. CLookup.prototype.GetTLA = function(oAcronym)
  514. {
  515.   var sChar = "";
  516.   var sRest = "";
  517.   var sRet = "";
  518.   var sTLA = "";
  519.   var nLen = 0;
  520.   var oAc = null;
  521.   var bPlDone = false;
  522.  
  523.   if (oAcronym)
  524.   {
  525.     this._sTLA = "";
  526.     oAc = oAcronym;
  527.   }
  528.   else
  529.     oAc = this._oAcronym;
  530.  
  531.   if (this._bTLAPlural && oAc.selectSingleNode("primaryp"))
  532.     bPlDone = this.MakeTLAP(oAc);
  533.   else
  534.     this.MakeTLA(oAc);
  535.  
  536.   if (this._bTLACap)
  537.   {
  538.     sTLA = this._sTLA;
  539.     sChar = sTLA.substr(0,1);
  540.     sRest = sTLA.substr(1);
  541.     this._sTLA = sChar.toUpperCase() + sRest;
  542.   }
  543.  
  544.   if (!bPlDone && this._bTLAPlural)
  545.   {
  546.     sTLA = this._sTLA;
  547.     nLen = sTLA.length;
  548.     sChar = sTLA.substr(nLen-1,1);
  549.     sChar = sChar.toLowerCase();
  550.     switch (sChar)
  551.     {
  552.       case "x":
  553.       case "s":
  554.         sRest = "es";
  555.         break;
  556.       default:
  557.         sRest = "s";
  558.         break;
  559.     }
  560.     this._sTLA = sTLA + sRest;
  561.   }
  562.  
  563.   return this._sTLA;
  564. }
  565.  
  566. // Find TLA and return its substitution string.
  567. // Called directly from XSL. //at
  568. CLookup.prototype.TLA = function(sRid)
  569. {
  570.   var sTLA = "";
  571.   var oAc = null;
  572.  
  573.   this._sTLA = "";
  574.   this._oAcronym = null;
  575.   this._bTLACap = false;
  576.   this._bTLAPlural = false;
  577.  
  578.   if (sRid)
  579.   {
  580.     oAc = this.RetrieveAcronym(sRid);
  581.     if (oAc)
  582.     {
  583.       this._oAcronym = oAc;
  584.       sTLA = this.GetTLA();
  585.     }
  586.   }
  587.  
  588.   return sTLA;
  589. }
  590.  
  591.  
  592. // convert the attribs of the target node to properties of a
  593. // JS object and store the target node in hash.
  594. CLookup.prototype.CacheItem = function(sRID, bNoIncRefs)
  595. {
  596.   var oTNode;
  597.   if (!(oTNode = this.RetrieveTarget(sRID)))
  598.   {
  599.     return null;
  600.   }
  601.  
  602.   return new CCacheItem(oTNode, (bNoIncRefs ? 0 : 1));
  603.   //return (this._cache[sRID] = new CCacheItem(oTNode, (bNoIncRefs ? 0 : 1)));
  604. }
  605.  
  606. // given an id, lookup the corresponding target
  607. // sRID - the ID of the desired topic (no default)
  608. // oDest - where to put the results of the lookup (no default)
  609. // bNoIncRefs - whether or not this lookup should count toward a reference (default is false)
  610. // sCurLang - the desired devlang for the lookup (default is the global devlang)
  611. // sOID - disambiguate the desired interface or object id (depending on the devlang) of the member (no default)
  612. //        if "auto" is specified, the primary/active interface of the current topic is used
  613. CLookup.prototype.LookupByRID = function(sRID, oDest, bNoIncRefs, sCurLang, sOID)
  614. {
  615.   if (!sCurLang)
  616.   {
  617.     sCurLang = this._oCtx._devlang;
  618.   }
  619.  
  620.   var oSrc = new CSimpleSrc(sRID, sCurLang);
  621.   if (sOID)
  622.   {
  623.     this.AddOID(oSrc, sOID);
  624.   }
  625.  
  626.   return this.Lookup(oSrc, oDest, bNoIncRefs);
  627. }
  628.  
  629. // adorn the source object with the requested iid or auto qualifier
  630. // this helps to resolve otherwise ambiguous xrefs
  631. CLookup.prototype.AddOID = function(oSrc, sOID)
  632. {
  633.   var sAttr = null, sCurLang = oSrc.devlang;
  634.   if (sOID == 'auto')
  635.   {
  636.     if (sAttr = gaMapAuto[sCurLang])
  637.     {
  638.       oSrc[sAttr] = 1;
  639.     }
  640.   }
  641.   else if (sAttr = gaMapAttr[sCurLang])
  642.   {
  643.     oSrc[sAttr] = sOID;
  644.   }
  645. }
  646.  
  647. // Lookup the target referenced by oNode.
  648. // Assumption here is that oNode is an XML DOM node that exposes a @rid.
  649. // CONSIDER: Support sKey parameter so that topic id can be
  650. // identified by some attr other than @rid.
  651. CLookup.prototype.LookupByNode = function(oNode, oDest, bNoIncRefs, sOID)
  652. {
  653.   if (!oNode)
  654.   {
  655.     this._error = "null node passed to LookupByNode";
  656.     return false;
  657.   }
  658.  
  659.   var sRID = oNode.getAttribute("rid");
  660.   if (!sRID)
  661.   {
  662.     this._error = "@rid not found on " + oNode.nodeName;
  663.     return false;
  664.   }
  665.  
  666.   var oObj = Node2Object(oNode);
  667.   if (!oObj)
  668.   {
  669.     return false;
  670.   }
  671.  
  672.   if (!oObj.devlang)
  673.   {
  674.     oObj.devlang = this._oCtx._devlang;
  675.   }
  676.  
  677.   // only attach the source node if it's an xref
  678.   if ("xref" == oNode.nodeName.toLowerCase())
  679.   {
  680.     oObj._srcNode = oNode;
  681.   }
  682.   else
  683.   {
  684.     // this param will never be passed in the typical xref case
  685.     // it will likely be passed in the iface/imembers case
  686.     if (sOID)
  687.     {
  688.       this.AddOID(oObj, sOID);
  689.     }
  690.   }
  691.  
  692.   //special processing for xrefs with qualify='0' attribute
  693.   //added by petertay for GDI+ - note that this a total hack, but it would take too long to implement properly
  694.       if("xref" == oNode.nodeName.toLowerCase())
  695.     {
  696.         //check current xref for qualify attribute
  697.         if(oNode.getAttribute("qualify")=="0")
  698.         {
  699.             //it's okay to go ahead and do the lookup 
  700.             var bReturn = this.Lookup(oObj, oDest, bNoIncRefs);
  701.             var compString = oDest._caption;
  702.             var _index = compString.indexOf("::");
  703.             if (_index == "-1")
  704.             {
  705.                 //this is an error, there is no scope operator in the name attribute on the targ
  706.                 this._error = "qualify attribute used with non-qualified target name - check name in targets2.xml";
  707.                 return false;
  708.             }
  709.             else
  710.             {
  711.                 oDest._caption = compString.substring(_index+2,compString.length);
  712.             }
  713.             return bReturn;
  714.         }
  715.         //no qualify attribute on the xref, continue normally
  716.         else
  717.         {
  718.             return this.Lookup(oObj, oDest, bNoIncRefs);
  719.         }
  720.     }
  721.     //this was not an xref, go ahead and do the lookup as requested
  722.     else
  723.     { 
  724.         return this.Lookup(oObj, oDest, bNoIncRefs);
  725.     }
  726.  
  727. }
  728.  
  729. // look for a target by name. This is slow (!!!) because
  730. // topics are not indexed by name.
  731. //at *** Rewritten for LuCache backend.
  732. // sName - the @name of the topic
  733. // oDest - js object used to store results
  734. // sCriteria - optional string used to help refine the query
  735. CLookup.prototype.LookUpByName = function(sName, oDest, sCriteria)
  736. {
  737.   var bOk = false;
  738.   var sTargXML = null;
  739.   var sTPath = this._oCtx._sDrive + this._oCtx.GetPathOf("targets");
  740.   var oTNodes = null;
  741.   var oTNode = null;
  742.   var oData = null;
  743.   var bLuCache = this._oCtx.CacheLookups();
  744.  
  745.   oData = this.EnsureData(bLuCache);
  746.   bLuCache = this._oCtx.CacheLookups();
  747.  
  748.   oDest.Init();
  749.  
  750.   if (sName)
  751.   {
  752.     oDest.SetCaption(sName);
  753.  
  754.     sCriteria = NormalizeCriteria(sCriteria);
  755.  
  756.     if (bLuCache && oData)
  757.     {
  758.       // Try to use the LuCache Lookup Cache.
  759.       try
  760.       {
  761.         // Call LuCache to lookup the name and get back the node-xml.
  762.         sTargXML = oData.LookupField(sName, "name", sTPath, sCriteria);
  763.       }
  764.       catch(e)
  765.       {
  766.         sTargXML = null;
  767.       }
  768.       if (sTargXML)
  769.       {
  770.         var oTDom = this._oCtx._oTDom;
  771.  
  772.         // Now use mini-dom node to load node-xml and get a node.
  773.         oTDom.async = false;
  774.         oTDom.loadXML(sTargXML);
  775.         oTNode = oTDom.documentElement;
  776.         if (oTNode)
  777.           bOk = true;
  778.         else
  779.           this._error = "cannot load node xml.";
  780.       }
  781.       else
  782.         this._error = "cannot locate " + sName;
  783.     }
  784.     else
  785.     {
  786.       // Try to use a loaded DOM for lookups.
  787.       if (bLuCache && !oData)
  788.         oData = this.EnsureData(false);
  789.       if (oData)
  790.       {
  791.         oTNodes = oData.selectNodes("/inetsdk:targets/targ[@name='" + sName + "']" + sCriteria);
  792.         if (oTNodes && oTNodes.length)
  793.         {
  794.           // BUGBUG: If we get back more than one, how do we disambiguate
  795.           // beyond sCriteria?
  796.           oTNode = oTNodes[0];
  797.           if (oTNode)
  798.             bOk = true;
  799.           else
  800.             this._error = "cannot locate " + sName;
  801.         }
  802.       }
  803.       else
  804.         this._error = "cannot create access to targets.";
  805.     }
  806.   }
  807.  
  808.   if (bOk)
  809.   {
  810.     var sRID = oTNode.getAttribute("id");
  811.     if (sRID)
  812.     {
  813.       var oSrc = new CSimpleSrc(sRID, this._oCtx._devlang);
  814.       var oCacheItem = this.RetrieveCachedItem(sRID, true);
  815.       if (oCacheItem)
  816.         bOk = this.BuildHREF(oSrc, oDest, oCacheItem);
  817.       else
  818.         bOk = false;
  819.     }
  820.     else
  821.     {
  822.       // wasted check. should never happen acc. DTD
  823.       this._error = "missing @rid";
  824.       bOk = false;
  825.     }
  826.   }
  827.  
  828.   return bOk;
  829. }
  830.  
  831. CLookup.prototype.BuildExtendedId = function(oSrc, oDest, oCacheItem){
  832.     var result = "";
  833.     var sDevLang = "";
  834.     
  835.     dp = oDest._ionodes.context.selectSingleNode(oDest._ionodes.expr);    // this is the deployment used.
  836.     
  837.     dp.getAttribute("hack") ? sDevLang = "scr" : sDevLang = dp.parentNode.getAttribute("value");
  838.     if (sDevLang == "none") sDevLang = "";
  839.     
  840.     // must make the extended id.  this id is derived from information about the link.
  841.     if(sDevLang == 'cpp' && dp.getAttribute("rid")){
  842.         result = result + dp.getAttribute("rid");
  843.     }
  844.     result = result + oSrc.rid;
  845.     
  846.     if (sDevLang != "") {
  847.         result = result + "_" + sDevLang;
  848.     }
  849.     
  850.     if(result){
  851.         oDest._extendedRid = result;
  852.     }
  853.  
  854. //  <META NAME="MS-HAID"><xsl:attribute name="CONTENT">
  855. //<xsl:choose>
  856. //<xsl:when test=".[/inetsdk:topic/metadata/applies/iface $and$ &var_devlang;='cpp']">
  857. //  <xsl:choose>
  858. //  <xsl:when test="/inetsdk:topic/metadata/applies/iface[@primary]"><xsl:value-of select="/inetsdk:topic/metadata/applies/iface[@primary]/@rid"/></xsl:when>
  859. //  <xsl:otherwise><xsl:value-of select="/inetsdk:topic/metadata/applies/iface/@rid"/></xsl:otherwise>
  860. //  </xsl:choose>
  861. //</xsl:when>
  862. //<xsl:when test=".[/inetsdk:topic/metadata/applies/object $and$ &var_devlang;='vb']">
  863. //  <xsl:choose>
  864. //  <xsl:when test="/inetsdk:topic/metadata/applies/object[@primary]"><xsl:value-of select="/inetsdk:topic/metadata/applies/object[@primary]/@rid"/></xsl:when>
  865. //  <xsl:otherwise><xsl:value-of select="/inetsdk:topic/metadata/applies/object/@rid"/></xsl:otherwise>
  866. //  </xsl:choose>
  867. //</xsl:when>
  868. ///</xsl:choose><xsl:value-of select="/inetsdk:topic/metadata/@id"/>&var_suffix;</xsl:attribute></META>
  869.  
  870.     return result;
  871. }
  872.  
  873. // use the metadata to fake a lookup
  874. // metadata is *mostly* polymorphic with a target node. No hrefs in metadata
  875. // This replaces GetMetaData
  876. // oNode - represents an xref when called from xref.xsl. Can be null
  877. // oDest - represents the destination object in which to cache results
  878. CLookup.prototype.LookupLocal = function(oNode, oDest)
  879. {
  880.   var oCtx = this._oCtx;
  881.   var oDoc = oCtx.GetDocument();
  882.   if (!oDoc)
  883.   {
  884.     this._error = "document reference unavailable in LookupLocal";
  885.     return false;
  886.   }
  887.  
  888.   var oMDNode = oDoc.selectSingleNode('/inetsdk:topic/metadata');
  889.   if (!oMDNode)
  890.   {
  891.     this._error = 'unable to locate metadata';
  892.     return false;
  893.   }
  894.  
  895.   var oSrcObj = null;
  896.   if (oNode)
  897.   {
  898.     oSrcObj = Node2Object(oNode);
  899.     if (!oSrcObj)
  900.     {
  901.       return false;
  902.     }
  903.  
  904.     if (!oSrcObj.devlang)
  905.     {
  906.       oSrcObj.devlang = oCtx.GetDevLang();
  907.     }
  908.   }
  909.   else
  910.   {
  911.     // no xref node was passed in, so cook up up
  912.     oSrcObj = new CSimpleSrc(oMDNode.getAttribute("id"), oCtx.GetDevLang());
  913.   }
  914.  
  915.   oSrcObj.self = true; // this is a self-reference
  916.  
  917.   oDest.Init();
  918.  
  919.   var oCacheItem = new CCacheItem(oMDNode, 0);
  920.  
  921.   oDest.SetItem(oSrcObj.rid, oCacheItem);
  922.  
  923.   // only attach the source node if it's an xref
  924.   if ("xref" == oNode.nodeName.toLowerCase())
  925.   {
  926.     oSrcObj._srcNode = oNode;
  927.   }
  928.  
  929.   if (!this.ExtractCaption(oSrcObj, oDest, oCacheItem))
  930.   {
  931.     return false;
  932.   }
  933.  
  934.   return true;
  935. }
  936.  
  937. // Lookup the xref referenced by oSrc.
  938. // bNoIncRefs  - if true, the reference count for the target is not incremented
  939. CLookup.prototype.Lookup = function(oSrc, oDest, bNoIncRefs)
  940. {
  941.   if (!oDest)
  942.   {
  943.     this._error = "Lookup: null destination data object";
  944.     return false;
  945.   }
  946.  
  947.   if (!oSrc)
  948.   {
  949.     this._error = "Lookup: null source data object";
  950.     return false;
  951.   }
  952.  
  953.   if (this._fBadDataSrc)
  954.   {
  955.     return false;
  956.   }
  957.  
  958.   this.ClearError();
  959.  
  960.   oDest.Init(); // clear out volatile data from the destination data object
  961.  
  962.   var sRID = oSrc.rid;
  963.   if (!sRID)
  964.   {
  965.     this._error = "@rid missing " + (oSrc._nodeName ? " on " + oSrc._nodeName : "");
  966.     return false;
  967.   }
  968.  
  969.   var oCacheItem = this.RetrieveCachedItem(sRID, bNoIncRefs);
  970.   if (!oCacheItem)
  971.   {
  972.     return false;
  973.   }
  974.  
  975.   oDest.SetItem(sRID, oCacheItem);
  976.  
  977.   if (!oSrc.devlang)
  978.   {
  979.     oSrc.devlang = this._oCtx._devlang;
  980.   }
  981.  
  982.   if (!this.ExtractCaption(oSrc, oDest, oCacheItem))
  983.   {
  984.     return false;
  985.   }
  986.  
  987.   if (!this.BuildHREF(oSrc, oDest, oCacheItem))
  988.   {
  989.     return false;
  990.   }
  991.  
  992.   if (!this.BuildExtendedId(oSrc, oDest, oCacheItem)){
  993.     return false;
  994.   }
  995.  
  996.   return true;
  997. }
  998.  
  999. CLookup.prototype.HasOverridingCaption = function(oSrc)
  1000. {
  1001.   var oRequest;
  1002.   return (((oRequest = oSrc._srcNode) && oRequest.firstChild) ? true : false);
  1003. }
  1004.  
  1005. CLookup.prototype.GetOverridingCaption = function(oSrc)
  1006. {
  1007.   var sCaption = "";
  1008.   var oTLA = null;
  1009.   var oRequest = oSrc._srcNode;
  1010.  
  1011.   if (oRequest)
  1012.   {
  1013.     //at: Add support for nested TLA in the overriding caption.
  1014.   //Assumption is that if an xref contains a tla, the tla precedes any text
  1015.     oTLA = oRequest.selectSingleNode("tla");
  1016.     if (oTLA)
  1017.     {
  1018.       if (this.IsTLA(oTLA))
  1019.         sCaption = this.GetTLA();
  1020.       if (oRequest.text)
  1021.       sCaption += " ";
  1022.     }
  1023.  
  1024.     if (oRequest.text)
  1025.     {
  1026.       sCaption += oRequest.text;
  1027.     }
  1028.   }
  1029.  
  1030.   return sCaption;
  1031. }
  1032.  
  1033. /*
  1034.  Extract the caption from the data source
  1035.  
  1036.  oSrc - js object representing the source data requesting the link
  1037.  oCacheItem - js object representing the target node representing the link
  1038. */
  1039. CLookup.prototype.ExtractCaption = function(oSrc, oDest, oCacheItem)
  1040. {
  1041.   // BUGBUG: Neglects the possibility of markup descending from the xref (e.g. img)
  1042.   var oTNode = oCacheItem._targetNode;
  1043.   var sTPN = oCacheItem._pn;
  1044.   var bObj = (oSrc._nodeName && ("object" == oSrc._nodeName.toLowerCase()));
  1045.   var oDLNode;
  1046.  
  1047.   // first check if author has provided custom innerText for link
  1048.   // requires that the source XML node be attached to the source object
  1049.   if (this.HasOverridingCaption(oSrc))
  1050.   {
  1051.     oDest.SetCaption(this.GetOverridingCaption(oSrc));
  1052.     return true;
  1053.   }
  1054.  
  1055.   // Look for persistent name in targ
  1056.   // if: xref rid="..." type="pn"
  1057.   if (oSrc.type && ("pn" == oSrc.type))
  1058.   {
  1059.     if (!sTPN)
  1060.     {
  1061.       this._error = "target does not specify requested @pn.";
  1062.       return false;
  1063.     }
  1064.     else
  1065.     {
  1066.       oDest.SetCaption(sTPN);
  1067.     }
  1068.   }
  1069.   else
  1070.   {
  1071.     var sSubQuery;
  1072.  
  1073.     //markda: special processing if we are using targets V2.
  1074.     if ( this._oCtx.UseTargetsV2() && !oSrc.self )
  1075.     {
  1076.       sSubQuery = "/dp_info[@name]";
  1077.     }
  1078.     else
  1079.     {
  1080.       sSubQuery = "[@name]";
  1081.     }
  1082.  
  1083.     oDLNode = oTNode.selectSingleNode(gaDLangMap[(oSrc.self ? 'self' : 'ext')] + "[@value='" + oSrc.devlang + "']" + sSubQuery);
  1084.     if (oDLNode)
  1085.     {
  1086.       //markda: if there's a devlang-specific caption, use it.
  1087.       oDest.SetCaption(oDLNode.getAttribute("name"));
  1088.     }
  1089.     else
  1090.     {
  1091.       //at: Else if we're processing an object (eg, xrefs in AppliesTo),
  1092.       //at: then use the persistent name if the targ has one;
  1093.       //at: otherwise use the normal name.  Note that this logic
  1094.       //at: assumes that pn has the correct upper/lower case for
  1095.       //at: items like INPUT type=button.
  1096.       if (bObj && sTPN)
  1097.         oDest.SetCaption(sTPN);
  1098.       else
  1099.         oDest.SetCaption(oCacheItem._name);
  1100.     }
  1101.   } //markda
  1102.  
  1103.   // only attempt to extend the caption if the href is not at the targ level.
  1104.   // href on a targ indicates language neutrality or legacy HTM/ASP.
  1105.   if (!oCacheItem._href)
  1106.   {
  1107.     var sPageType = oCacheItem._type, sDevLang = oSrc.devlang;
  1108.  
  1109.     if ((oSrc.type != 'pn') && (sDevLang == "cpp") && (sPageType == "method" || sPageType == "property" || sPageType == "collection" || sPageType == "event"))
  1110.     {
  1111.       // Look for an iface/object prefix
  1112.       if (!this.GetExtendedCaption(oSrc, oDest, oCacheItem))
  1113.       {
  1114.         return false;
  1115.       }
  1116.     }
  1117.   }
  1118.  
  1119.   return true;
  1120. }
  1121.  
  1122. CLookup.prototype.GetExtendedCaption = function(oSrc, oDest, oCacheItem)
  1123. {
  1124.   // BUGBUG: if this is a property, prepend the put/get if C++??
  1125.   var oNodes = null;
  1126.   if (!(oNodes = this.EnsureIONodes(oSrc, oDest, oCacheItem)))
  1127.   {
  1128.     return false;
  1129.   }
  1130.   else if (oNodes.length == 1)
  1131.   {
  1132.     return this.GatherTargetData(oSrc, oDest, oNodes[0]);
  1133.   }
  1134.   else // (oNodes.length > 1)
  1135.   {
  1136.     if (oSrc.self) // the @primary check only works in the self-reference case
  1137.     {
  1138.       var sIOQuery = "applies/" + gaMapLang2SubNode[oSrc.devlang] + "[@primary]";
  1139.       var oNode = oCacheItem._targetNode.selectSingleNode(sIOQuery);
  1140.       if (oNode)
  1141.       {
  1142.         return this.GatherTargetData(oSrc, oDest, oNode);
  1143.       }
  1144.       else
  1145.       {
  1146.         this.GatherTargetData(oSrc, oDest, oNodes[0]);
  1147.         return true;
  1148.       }
  1149.     }
  1150.     else
  1151.     {
  1152.       this._error = "ambiguous xref; must specify @iid, @oid, or @primary.";
  1153.       return false;
  1154.     }
  1155.   }
  1156.  
  1157. }
  1158.  
  1159. CLookup.prototype.GatherTargetData = function(oSrc, oDest, oNode)
  1160. {
  1161.   var sIOCaption = oNode.getAttribute("name");
  1162.   if (sIOCaption)
  1163.   {
  1164.     oDest.SetCaption(sIOCaption);
  1165.   }
  1166.   else
  1167.   {
  1168.   //markda: attribute optional for targets V2
  1169.   var sRID;
  1170.     if ( sRID = oNode.getAttribute("rid") )
  1171.     {
  1172.   //markda: end
  1173.       // The following code executes when the target node (oNode) is actually part of the topic/metadata (self-reference case)
  1174.       // In that case we need to do a lookup because the redundant data is not stored there
  1175.       var sRID = oNode.getAttribute("rid");
  1176.       var oIONode = this.RetrieveTarget(sRID);
  1177.       if (!oIONode)
  1178.       {
  1179.         // this._error = gaMapLang2SubNode[oSrc.devlang] + "'" + sRID + "' not found."
  1180.         return false;
  1181.       }
  1182.  
  1183.       // pre-pend the appropriate scope operator
  1184.       // @petertay UNLESS there is a qualify="0" attribute on the xref
  1185.       if(oSrc.qualify=="0")
  1186.       {
  1187.           oDest.SetCaption(oDest.GetCaption());
  1188.         }
  1189.         else
  1190.         {
  1191.             oDest.SetCaption(oIONode.getAttribute("name") + gaMapScope[oSrc.devlang] + oDest.GetCaption());
  1192.         }
  1193.     }
  1194.     //markda: if using targets V2, use targ[@name] if no dp_info[@name]
  1195.     else
  1196.   {
  1197.     if ( this._oCtx.UseTargetsV2()
  1198.            && (sIOCaption = oNode.parentNode.parentNode.getAttribute("name")) )
  1199.       {
  1200.         oDest.SetCaption(sIOCaption);
  1201.       }
  1202.     }
  1203.   }
  1204.   //markda: end
  1205.  
  1206.   return true;
  1207. }
  1208.  
  1209. // Build a query to drill into the target, and return the collection of nodes that qualify
  1210. CLookup.prototype.EnsureIONodes = function(oSrc, oDest, oCacheItem)
  1211. {
  1212.   // self base query: applies/iface[@rid=''] or applies/object[@rid='']
  1213.   // extern base query: dlang[@value='cpp']/dp_iface or dlang[@value='vb']/dp_object
  1214.   //markda: for targets V2: dlang[@value='cpp']/dp_info or dlang[@value='vb']/dp_info
  1215.  
  1216.   var sDevLang = oSrc.devlang;
  1217.  
  1218.   //markda: with targets V2, all devlangs have subnodes
  1219.   if ( ! this._oCtx.UseTargetsV2() )
  1220.   {
  1221.   //markda: end
  1222.     // no need to check for iface/object for this devlang
  1223.     if (typeof(gaMapLang2SubNode[sDevLang]) == 'undefined')
  1224.     {
  1225.       this._error = "devlang '" + sDevLang + "' doesn't support subnodes.";
  1226.       return null;
  1227.     }
  1228.   } //markda
  1229.  
  1230.   if (oDest._ionodes)
  1231.   {
  1232.     return oDest._ionodes;
  1233.   }
  1234.  
  1235.   var sIOQuery;
  1236.  
  1237.   if (oSrc.self)
  1238.   {
  1239.     sIOQuery = "applies/" + gaMapLang2SubNode[sDevLang];
  1240.   }
  1241.   else
  1242.   {
  1243.     //markda: determine if we are using targets V1 or V2
  1244.     if ( this._oCtx.UseTargetsV2() )
  1245.     {
  1246.     if ( sDevLang == "" )
  1247.         sDevLang = "none";
  1248.       sIOQuery = "dlang[@value='" + sDevLang + "']/dp_info";
  1249.     }
  1250.     else //markda: end
  1251.       sIOQuery = "dlang[@value='" + sDevLang + "']/dp_" + gaMapLang2SubNode[sDevLang];
  1252.   }
  1253.  
  1254.   // check if the author has specified an @iid or @oid on the xref
  1255.   if (typeof(gaMapAttr[sDevLang]) != 'undefined'  && oSrc)
  1256.   {
  1257.     // attempt to qualify the query so as to avoid an ambiguous xref
  1258.  
  1259.     var sAttr, sVal, sIORID = null;
  1260.     // use the @iid or @oid if one has been specified
  1261.     if ( (sAttr = gaMapAttr[sDevLang]) && (sVal = oSrc[sAttr]) )
  1262.     {
  1263.       sIORID = sVal;
  1264.     }
  1265.     // otherwise attempt to autoresolve if the author gave us permission
  1266.     else if ( (sAttr = gaMapAuto[sDevLang]) && oSrc[sAttr] )
  1267.     {
  1268.  
  1269.       var oIFaces;
  1270.       var sPageType = GetPageType(); // get the type of the current doc
  1271.       if (sPageType && (sPageType == "iface"))
  1272.       {
  1273.         var oIFaceID = ownerDocument.selectSingleNode("/inetsdk:topic/metadata/@id");
  1274.         if (!oIFaceID)
  1275.         {
  1276.           this._error = "interface page doesn't specify an id";
  1277.           return false;
  1278.         }
  1279.         else
  1280.         {
  1281.           sIORID = oIFaceID.value;
  1282.         }
  1283.       }
  1284.       // use the primary iid of the current topic
  1285.       else if ( (oIFaces = ownerDocument.selectNodes("/inetsdk:topic/metadata/applies/" + gaMapLang2SubNode[sDevLang] + "[@rid $and$ @primary]") ) && oIFaces.length == 1)
  1286.       {
  1287.         sIORID = oIFaces[0].getAttribute("rid");
  1288.       }
  1289.       else if ( (oIFaces = ownerDocument.selectNodes("/inetsdk:topic/metadata/applies/" + gaMapLang2SubNode[sDevLang] + "[@rid]")) && oIFaces.length == 1)
  1290.       {
  1291.         sIORID = oIFaces[0].getAttribute("rid");
  1292.       }
  1293.     }
  1294.  
  1295.     if (sIORID)
  1296.     {
  1297.       sIOQuery += "[@rid='" + sIORID + "']";
  1298.     }
  1299.   }
  1300.  
  1301.   // query for the iface/object nodes below the target
  1302.   var oNodes = oCacheItem._targetNode.selectNodes(sIOQuery);
  1303.   if (!oNodes || !oNodes.length)
  1304.   {
  1305.     //markda: attempt to get generic target
  1306.     if ( this._oCtx.UseTargetsV2() )
  1307.     {
  1308.       oNodes = oCacheItem._targetNode.selectNodes( "dlang/dp_info" );
  1309.       if (!oNodes || !oNodes.length)
  1310.       {
  1311.         this._error = "query failure after retry! [" + sIOQuery + "]";
  1312.         return null;
  1313.       }
  1314.     }
  1315.     else
  1316.     {  //markda: end
  1317.       this._error = "query failure! [" + sIOQuery + "]";
  1318.       return null;
  1319.     } //markda
  1320.   }
  1321.  
  1322.   return (oDest._ionodes = oNodes);
  1323. }
  1324.  
  1325. CLookup.prototype.GetError = function()
  1326. {
  1327.   return this._error;
  1328. }
  1329.  
  1330. CLookup.prototype.IsType = function(o, oDest, sCompareType)
  1331. {
  1332.   if (!this.LookupByNode(o, oDest, true))
  1333.   {
  1334.     return false;
  1335.   }
  1336.  
  1337.   var sType = oDest.GetType();
  1338.   return (sType == sCompareType ? true : false);
  1339. }
  1340.  
  1341. // load the data source used to perform lookups
  1342. //at *** Rewritten for LuCache.
  1343. CLookup.prototype.EnsureData = function(bLuCache)
  1344. {
  1345.   var oData = null;
  1346.   var sError = "";
  1347.  
  1348.   // BUGBUG: What if object is created but data can't be loaded
  1349.   if (typeof(this._data) == 'undefined')
  1350.   {
  1351.     // Determine if LuCache is out there.
  1352.     try
  1353.     {
  1354.       oData = new ActiveXObject("LuCache.Lookup");
  1355.     }
  1356.     catch(e)
  1357.     {
  1358.       sError = "cannot instantiate LuCache. " + e.description;
  1359.     }
  1360.  
  1361.     if (bLuCache)
  1362.     {
  1363.       // Try to use the LuCache fast lookup cache.
  1364.       if (oData)
  1365.         this._data = oData;
  1366.       else
  1367.       {
  1368.         this._error = sError;
  1369.         this._oCtx.NoCacheLookups();
  1370.       }
  1371.     }
  1372.  
  1373.     if (!this._data)
  1374.     {
  1375.       // Try to use an XML DOM.
  1376.       try
  1377.       {
  1378.         this._data = new ActiveXObject("MSXML.DOMDocument");
  1379.       }
  1380.       catch(e)
  1381.       {
  1382.         this._error = "cannot instantiate MSXML. " + e.description;
  1383.         return null;
  1384.       }
  1385.  
  1386.       this._data.async = false;
  1387.       this._data.load(this._oCtx.GetPathOf("targets"));
  1388.       var oPErr = this._data.parseError;
  1389.       if (oPErr.errorCode != 0)
  1390.       {
  1391.         this._error = oPErr.url + "(" + oPErr.line + "): Targets lookup error: " + oPErr.reason.replace(/[\n\r]/g,"");
  1392.         this._fBadDataSrc = true;
  1393.         return null;
  1394.       }
  1395.     }
  1396.   }
  1397.   else if (this._fBadDataSrc)
  1398.   {
  1399.     return null;
  1400.   }
  1401.  
  1402.   //at+ Add code here to check for parse error during load of targets.xml.
  1403.   //at+ This would require a new method, ILookup::GetError.
  1404.  
  1405.   return this._data;
  1406. }
  1407.  
  1408. // Ensure topic info (topinfo.xml) is available for retrieval. //at
  1409. CLookup.prototype.EnsureTIData = function(bLuCache)
  1410. {
  1411.   var oData = null;
  1412.   var sError = "";
  1413.  
  1414.   if (typeof(this._tidata) == 'undefined')
  1415.   {
  1416.     // Determine if LuCache is out there.
  1417.     try
  1418.     {
  1419.       oData = new ActiveXObject("LuCache.Lookup");
  1420.     }
  1421.     catch(e)
  1422.     {
  1423.       sError = "cannot instantiate LuCache. " + e.description;
  1424.     }
  1425.  
  1426.     if (bLuCache)
  1427.     {
  1428.       // Try to use the LuCache fast lookup cache.
  1429.       if (oData)
  1430.         this._tidata = oData;
  1431.       else
  1432.       {
  1433.         this._error = sError;
  1434.         this._oCtx.NoCacheLookups();
  1435.       }
  1436.     }
  1437.  
  1438.     if (!this._tidata)
  1439.     {
  1440.       // Try to use an XML DOM.
  1441.       try
  1442.       {
  1443.         this._tidata = new ActiveXObject("MSXML.DOMDocument");
  1444.       }
  1445.       catch(e)
  1446.       {
  1447.         this._error = "cannot instantiate MSXML. " + e.description;
  1448.         return null;
  1449.       }
  1450.  
  1451.       this._tidata.async = false;
  1452.       this._tidata.load(this._oCtx.GetPathOf("topinfo"));
  1453.       var oPErr = this._tidata.parseError;
  1454.       if (oPErr.errorCode != 0)
  1455.       {
  1456.         this._error = oPErr.url + "(" + oPErr.line + "): Topic Info lookup error: " + oPErr.reason.replace(/[\n\r]/g,"");
  1457.         this._fBadDataSrc = true;
  1458.         return null;
  1459.       }
  1460.     }
  1461.   }
  1462.   else if (this._fBadDataSrc)
  1463.   {
  1464.     return null;
  1465.   }
  1466.  
  1467.   return this._tidata;
  1468. }
  1469.  
  1470. // Ensure Acronyms data (acronyms.xml) is available for retrieval. //at
  1471. CLookup.prototype.EnsureAcData = function(bLuCache)
  1472. {
  1473.   var oData = null;
  1474.   var sError = "";
  1475.  
  1476.   if (typeof(this._acdata) == 'undefined')
  1477.   {
  1478.     // Determine if LuCache is out there.
  1479.     try
  1480.     {
  1481.       oData = new ActiveXObject("LuCache.Lookup");
  1482.     }
  1483.     catch(e)
  1484.     {
  1485.       sError = "cannot instantiate LuCache. " + e.description;
  1486.     }
  1487.  
  1488.     if (bLuCache)
  1489.     {
  1490.       // Try to use the LuCache fast lookup cache.
  1491.       if (oData)
  1492.         this._acdata = oData;
  1493.       else
  1494.       {
  1495.         this._error = sError;
  1496.         this._oCtx.NoCacheLookups();
  1497.       }
  1498.     }
  1499.  
  1500.     if (!this._acdata)
  1501.     {
  1502.       // Try to use an XML DOM.
  1503.       try
  1504.       {
  1505.         this._acdata = new ActiveXObject("MSXML.DOMDocument");
  1506.       }
  1507.       catch(e)
  1508.       {
  1509.         this._error = "cannot instantiate MSXML. " + e.description;
  1510.         return null;
  1511.       }
  1512.  
  1513.       this._acdata.async = false;
  1514.       this._acdata.load(this._oCtx.GetPathOf("acronyms"));
  1515.       var oPErr = this._acdata.parseError;
  1516.       if (oPErr.errorCode != 0)
  1517.       {
  1518.         this._error = oPErr.url + "(" + oPErr.line + "): TLA lookup error: " + oPErr.reason.replace(/[\n\r]/g,"");
  1519.         this._fBadDataSrc = true;
  1520.         return null;
  1521.       }
  1522.     }
  1523.   }
  1524.   else if (this._fBadDataSrc)
  1525.   {
  1526.     return null;
  1527.   }
  1528.  
  1529.   return this._acdata;
  1530. }
  1531.  
  1532. CLookup.prototype.BuildHREF = function(oSrc, oDest, oCacheItem)
  1533. {
  1534.   var oTNode = oCacheItem._targetNode;
  1535.   var sMedia = this._oCtx._media;
  1536.   var sChm = oTNode.getAttribute("chm");
  1537.   var sPerm = oTNode.getAttribute("perm");
  1538.   var sDelivery = oTNode.getAttribute("delivery");
  1539.   var sTargHREF = "";
  1540.   var isALink = false;
  1541.   var isHXSLink = false;
  1542.   var bHTTP = false;
  1543.  
  1544.     if(sDelivery && !sChm){
  1545.         this._error = "cannot have @delivery without @chm."
  1546.         return false;
  1547.     }
  1548.     
  1549.     if(sChm && !sPerm){
  1550.         this._error = "cannot have @chm without @perm."
  1551.         return false;
  1552.     }
  1553.     
  1554.   oDest._leave = "";
  1555.  
  1556.   oDest._hxslink = "";
  1557.   /* This section moved down (in modified form) to line 1533
  1558.   if (sMedia && sChm == "other")
  1559.   {
  1560.     switch (sMedia)
  1561.     {
  1562.       case "chm":
  1563.         // generate an ALINK if we're in CHM mode and are
  1564.         // linking to something in another CHM
  1565.         oDest._alink = oSrc.rid;
  1566.         // javascript: doesn't like ids that contain colons. Convert to "__"
  1567.         oDest._alinkproxy = oSrc.rid.replace(":","__");
  1568.         oDest.SetHREF("JavaScript:" + oDest._alinkproxy + ".Click()");
  1569.         oDest._leave = "chm";
  1570.         return true;
  1571.         break;
  1572.       case "hxs":
  1573.         //at: Assemble the Havana (Hxs) link if we're in CHM mode and are
  1574.         // linking to something in another CHM
  1575.         oDest._hxslink = '<MSHelp:link keywords="' + oSrc.rid + '" TABINDEX="0">' + oDest._caption + '</MSHelp:link>';
  1576.         oDest._leave = "chm";
  1577.         return true;
  1578.         break;
  1579.       default:
  1580.         break;
  1581.     }
  1582.   }
  1583.   */
  1584.  
  1585.   if (!this.ExtractHREF(oSrc, oDest, oCacheItem))
  1586.   {
  1587.     return false;
  1588.   }
  1589.  
  1590.   sTargHREF = oDest.GetHREF();
  1591.   bHTTP = /^http:\/\//i.test(sTargHREF);
  1592.  
  1593.   if (sMedia)
  1594.   {
  1595.     switch (sMedia)
  1596.     {
  1597.       case "chm":
  1598.           if(sPerm){
  1599.             if(sChm){
  1600.                 if(this._oCtx._delivery == "msdn"){
  1601.                     isALink = true;
  1602.                 } else if(this._oCtx._delivery == "psdk" && sDelivery == "psdk"){
  1603.                     isALink = true;
  1604.                 } else if(this._oCtx._delivery == "dx"){
  1605.                     // All PermTargs link to the web.
  1606.                 }
  1607.             }
  1608.         } else {
  1609.                 oDest._hxslink = "useless";
  1610.                 isHXSLink = true;
  1611.           }
  1612.  
  1613.         if(isALink){
  1614.             // generate an ALINK if we're in CHM mode and are
  1615.             // linking to something in another CHM
  1616.             oDest._alink = oSrc.rid;
  1617.             // javascript: doesn't like ids that contain colons. Convert to "__"
  1618.             oDest._alinkproxy = oSrc.rid.replace(":","__");
  1619.             oDest.SetHREF("JavaScript:" + oDest._alinkproxy + ".Click()");
  1620.             oDest._leave = "chm";
  1621.         }
  1622.  
  1623.         break;
  1624.       case "hxs":
  1625.         if (bHTTP)
  1626.         {
  1627.           oDest._leave = "ms";
  1628.         }
  1629.         else
  1630.         {
  1631.             if(sPerm){
  1632.                 if(sChm){
  1633.                     if(this._oCtx._delivery == "msdn"){
  1634.                         // peterril:  code that generates the mshelp:link will be defered until
  1635.                         // render time.
  1636.                         oDest._hxslink = "useless";        // just a placeholding to indicate that this
  1637.                                                         // is an hxs link.
  1638.                         isHXSLink = true;
  1639.                     } else if(this._oCtx._delivery == "psdk" && sDelivery == "psdk"){
  1640.                         oDest._hxslink = "useless";
  1641.                         isHXSLink = true;
  1642.                     } else if(this._oCtx._delivery == "dx"){
  1643.                         // All PermTargs link to the web.
  1644.                     }
  1645.                 }
  1646.             } else {
  1647.                 oDest._hxslink = "useless";
  1648.                 isHXSLink = true;
  1649.             }
  1650.         }
  1651.  
  1652.         break;
  1653.       default:
  1654.         break;
  1655.     }
  1656.   }
  1657.  
  1658.   if(!isHXSLink && !isALink && (sMedia == "chm" || sMedia == "hxs")){
  1659.     var sDomain = this._oCtx._domain;
  1660.     var sHREF = oDest.GetHREF();
  1661.  
  1662.     if(sDomain && sDomain != "null"){
  1663.         if(!bHTTP){
  1664.             // Need to prepend the domain onto the path for correct linking.
  1665.             sHREF = sDomain + sHREF;
  1666.             oDest.SetHREF(sHREF);
  1667.             return true;
  1668.         }
  1669.     }
  1670.   }
  1671.  
  1672.   // Prevent recursion. if this is a self-reference we're done.
  1673.   // Don't calculate a path relative to yourself!!
  1674.   if (goTD.IsSelf(oSrc.rid))
  1675.   {
  1676.     return true;
  1677.   }
  1678.  
  1679.   if (bHTTP)
  1680.   {
  1681.     if (sMedia && (sMedia == 'chm') && sChm && (sChm == 'other'))
  1682.     {  // Linking to another CHM
  1683.       oDest._leave = "chm";
  1684.       return true;
  1685.     }
  1686.     else if (sMedia && (sMedia == 'chm') && !sChm)
  1687.     {  // Linking to another CHM
  1688.       oDest._leave = "ms";
  1689.       return true;
  1690.     }
  1691.     else
  1692.     {
  1693.       // Search list of Microsoft sites
  1694.       var bFound = false;
  1695.       var len = gaMSSiteREs.length;
  1696.       for ( var i=0; i<len; i++ )
  1697.       {
  1698.         if ( gaMSSiteREs[i].test(sTargHREF) )
  1699.         { // Linking to a non-MS site
  1700.           bFound = true;
  1701.           break;
  1702.         }
  1703.       }
  1704.       if ( ! bFound )
  1705.       { // Linking to a non-MS site
  1706.         oDest._leave = "ms";
  1707.         return true;
  1708.       }
  1709.     }
  1710.   }
  1711.  
  1712.   if (!goTD.Ensure())
  1713.   {
  1714.     this._error = goTD.GetError();
  1715.     return false;
  1716.   }
  1717.  
  1718.  
  1719.   if (sMedia && (sMedia == 'chm'))
  1720.   {
  1721.     var sHREF;
  1722.     // BUGBUG: htm extension is hard-coded in the CHM case.
  1723.     sHREF = MakeRelative(goTD.GetHREF(), oDest.GetHREF());
  1724.     if (!sHREF)
  1725.     {
  1726.       this._error = "VROOT2Relative failure.";
  1727.       return false;
  1728.     }
  1729.     else
  1730.     {
  1731.       //Only change the target path if its extension is in the map.
  1732.       var sExt = JustExt(sHREF);
  1733.       if (sExt)
  1734.       {
  1735.         var sNewExt = gaExtMap[sExt];
  1736.         if (sNewExt)
  1737.         {
  1738.           sHREF = ChangeExt(sHREF, sNewExt);
  1739.         }
  1740.       }
  1741.  
  1742.       oDest.SetHREF(sHREF);
  1743.  
  1744.       return true;
  1745.     }
  1746.   }
  1747.  
  1748.   return true;
  1749.  
  1750. }
  1751.  
  1752. // extract the href from the target
  1753. CLookup.prototype.ExtractHREF = function(oSrc, oDest, oCacheItem)
  1754. {
  1755.   var oTNode = oCacheItem._targetNode;
  1756.   var sDevLang = oSrc.devlang;
  1757.   var sPageType = oCacheItem._type;
  1758.  
  1759.   var oHREF = null, oNodes = null, sHREF = null;
  1760.  
  1761.   //markda: special procesing if we are using targets V2
  1762.   if ( this._oCtx.UseTargetsV2() )
  1763.   {
  1764.     if ( oNodes = this.EnsureIONodes( oSrc, oDest, oCacheItem ) )
  1765.     {
  1766.       if (oNodes.length == 1)
  1767.       {
  1768.         sHREF = oNodes[0].getAttribute("href");
  1769.         if ( sHREF )
  1770.         {
  1771.           oDest.SetHREF( sHREF );
  1772.         }
  1773.         else
  1774.         {
  1775.           this._error = "@href missing from target subnode.";
  1776.           return false;
  1777.         }
  1778.       }
  1779.       else
  1780.       {
  1781.         this._error = "ambiguous xref; must specify @iid, @oid, or @primary.";
  1782.         return false;
  1783.       }
  1784.     }
  1785.     else
  1786.     {
  1787.       return false;
  1788.     }
  1789.   }
  1790.   else
  1791.   {
  1792.   //markda: end
  1793.     if (sDevLang == "") // generic topic
  1794.     {
  1795.       if (!(oDest.SetHREF(oTNode.getAttribute("href"))))
  1796.       {
  1797.         this._error = "@href missing on generic topic targ node.";
  1798.         return false;
  1799.       }
  1800.     }
  1801.  
  1802.     // check for @href on dlang <dlang value="scr" href="..."
  1803.     else if (oHREF = oTNode.selectSingleNode("dlang[@value='" + sDevLang + "']/@href"))
  1804.     {
  1805.       oDest.SetHREF(oHREF.value);
  1806.     }
  1807.     // check @href on dlang/dp_iface || dlang/dp_object
  1808.     else if (oNodes = this.EnsureIONodes(oSrc, oDest, oCacheItem))
  1809.     {
  1810.       if (oNodes.length == 1)
  1811.       {
  1812.         if (!oDest.SetHREF(oNodes(0).getAttribute("href")))
  1813.         {
  1814.           this._error = "@href missing from target subnode.";
  1815.           return false;
  1816.         }
  1817.       }
  1818.       else
  1819.       {
  1820.         this._error = "ambiguous xref; must specify @iid, @oid, or @primary.";
  1821.         return false;
  1822.       }
  1823.     }
  1824.     // check for href on targ first
  1825.     else if (sHREF = oTNode.getAttribute("href"))
  1826.     {
  1827.        // href directly on the targ
  1828.        oDest.SetHREF(sHREF)
  1829.     }
  1830.     else
  1831.     {
  1832.       this._error = "href missing on target node";
  1833.       return false;
  1834.     }
  1835.   }
  1836.  
  1837.   if (!this.CheckFragment(oSrc, oDest, oCacheItem))
  1838.   {
  1839.     //at: Enforce authoring of valid fids.
  1840.     this._error = "unknown fragment: fid='" + oSrc.fid + "'";
  1841.     return false;
  1842.   }
  1843.  
  1844.   return true;
  1845. }
  1846.  
  1847. CLookup.prototype.CheckFragment = function(oSrc, oDest, oCacheItem)
  1848. {
  1849.   if (!oSrc)
  1850.   {
  1851.     return true;
  1852.   }
  1853.  
  1854.   var sFid = oSrc.fid;
  1855.   if (sFid)
  1856.   {
  1857.     var oTNode = oCacheItem._targetNode;
  1858.  
  1859.     var oFrag = oTNode.selectSingleNode("frag[@id='" + sFid + "'][@caption]");
  1860.     if (oFrag)
  1861.     {
  1862.       oDest.SetHREF(oDest.GetHREF() + "#" + sFid);
  1863.       if (!this.HasOverridingCaption(oSrc))
  1864.       {
  1865.         oDest.SetCaption(oFrag.getAttribute("caption"));
  1866.       }
  1867.     }
  1868.     else
  1869.     {
  1870.       // BUGBUG: We can be a little more tolerant here since the page physically exists.
  1871.       //oDest._error = "Invalid fragment specifier '" + sFid + "'.";
  1872.       //at: oDest.SetHREF(oDest.GetHREF() + "#unknown_fragment");
  1873.       return false;
  1874.     }
  1875.   }
  1876.  
  1877.   return true;
  1878. }
  1879.  
  1880. // if the specified node refers to a namespace, cache the name
  1881. CLookup.prototype.IsNameSpaceRef = function(oSrcNode, sKey)
  1882. {
  1883.   this._nsinfo = new Object();
  1884.  
  1885.   if (!sKey)
  1886.   {
  1887.     sKey = "rid";
  1888.   }
  1889.  
  1890.   var sRID = oSrcNode.getAttribute(sKey);
  1891.   if (!sRID)
  1892.   {
  1893.     this._error = "unable to retrieve " + sKey + " from node."
  1894.     return false;
  1895.   }
  1896.  
  1897.   var oCacheItem = this.RetrieveCachedItem(sRID, true);
  1898.   if (!oCacheItem)
  1899.   {
  1900.     return false;
  1901.   }
  1902.  
  1903.   var oTNode = oCacheItem._targetNode;
  1904.   if (!oTNode)
  1905.   {
  1906.     return false;
  1907.   }
  1908.  
  1909.   var sType = oTNode.getAttribute("type");
  1910.   if (sType && sType == "namespace")
  1911.   {
  1912.     this._nsinfo["key"] = sRID;
  1913.     this._nsinfo["name"] = oTNode.getAttribute("name");
  1914.     return true;
  1915.   }
  1916.  
  1917.   return false;
  1918. }
  1919.  
  1920. // assuming the namespace has already been retrieved, return the specified attribute. only "name" is currently supported
  1921. CLookup.prototype.GetNameSpaceInfo = function(o, sAttr)
  1922. {
  1923.   // should never happen if IsNameSpaceRef is called first and return value is checked
  1924.   if (null == this._nsinfo || null == this._nsinfo[sAttr])
  1925.   {
  1926.     return "";
  1927.   }
  1928.  
  1929.   return this._nsinfo[sAttr];
  1930. }
  1931.  
  1932.  
  1933. // returns true if the ref topic applies to at least one object that has a persistent representation
  1934. function AppliesToPersistentHTMLObject()
  1935. {
  1936.   // peterril: commented out this condition because DHTML is defined for only the core DOM.  That means that
  1937.   //           all the other scripting events do not have this tech value.
  1938.   // BUGBUG: Only show this for HTML objects?
  1939.   //if (!ownerDocument.selectSingleNode("/inetsdk:topic/metadata/tech[@value='dhtml']"))
  1940.   //{
  1941.   //  return false;
  1942.   //}
  1943.  
  1944.   var oObjects = ownerDocument.selectNodes("/inetsdk:topic/metadata/applies/object/@rid");
  1945.   if (!oObjects || 0 == oObjects.length)
  1946.   {
  1947.     return false;
  1948.   }
  1949.  
  1950.   for (var i = 0; i < oObjects.length; i++)
  1951.   {
  1952.     var oTNode = goLookup.RetrieveTarget(oObjects[i].value);
  1953.     if (!oTNode)
  1954.     {
  1955.       continue;
  1956.     }
  1957.     else if (oTNode.getAttribute("pn")) // BUGBUG: Assumes XML for target data
  1958.     {
  1959.       return true;
  1960.     }
  1961.   }
  1962.  
  1963.   return false;
  1964. }
  1965.  
  1966. // Retrieve the type of the current topic
  1967. function GetPageType()
  1968. {
  1969.   var oTypeAttr;
  1970.   if (oTypeAttr = ownerDocument.selectSingleNode("/inetsdk:topic/metadata/@type"))
  1971.   {
  1972.     return (oTypeAttr.value);
  1973.   }
  1974.   else
  1975.   {
  1976.     return null;
  1977.   }
  1978. }
  1979.  
  1980. // Does sRID match the id of the current topic
  1981. function IsSelfReference(sRID)
  1982. {
  1983.   return ( (sRID == null || sRID == ownerDocument.selectSingleNode("/inetsdk:topic/metadata/@id").value) ? true : false);
  1984. }
  1985.  
  1986. // map the attributes of an XML DOM Node to the properties of a JScript object
  1987. function Node2Object(oNode, oObj, sPrefix)
  1988. {
  1989.   if (!oNode)
  1990.   {
  1991.     return null;
  1992.   }
  1993.  
  1994.   if (!oObj)
  1995.   {
  1996.     oObj = new Object();
  1997.   }
  1998.  
  1999.   var oAttrs = oNode.attributes;
  2000.   for (var i = 0; i < oAttrs.length; i++)
  2001.   {
  2002.     var oAttr = oAttrs(i)
  2003.     oObj[(sPrefix ? sPrefix : "") + oAttr.name] = oAttr.value;
  2004.   }
  2005.  
  2006.   oObj._nodeName = oNode.nodeName;
  2007.  
  2008.   return oObj;
  2009. }
  2010.  
  2011. // Ensure that the criteria string contains single quotes and is surrounded by square brackets
  2012. function NormalizeCriteria(sCriteria)
  2013. {
  2014.   if (typeof(sCriteria) != 'string')
  2015.   {
  2016.     return "";
  2017.   }
  2018.  
  2019.   sCriteria = sCriteria.replace(/"/g, "'");
  2020.   if (!/^\[/.test(sCriteria))
  2021.   {
  2022.     sCriteria = "[" + sCriteria;
  2023.   }
  2024.  
  2025.   if (!/\]$/.test(sCriteria))
  2026.   {
  2027.     sCriteria += "]";
  2028.   }
  2029.  
  2030.   return sCriteria;
  2031. }
  2032.  
  2033.  
  2034. /* XREF code END */
  2035. ]]>
  2036.